#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define SIZE 1024 //定义缓冲区数组大小
#define MAX_ARGC 64
#define SPC " "
char* argv[MAX_ARGC];
//关联环境变量,定义一个字符串，或者字符数组
char pwd[SIZE];
//存储新的环境变量
char env[SIZE];
//输出提示
const char* HostName()
{
	const char* hostname = getenv("HOSTNAME");
	if(hostname)
		return hostname;
}
const char* UserName()
{
	const char* username = getenv("USER");
	if(username)
		return username;
	else
		return "None";
}
const char* CurrentWorkDir()
{
	const char* cwd = getenv("PWD");
	if(cwd)return cwd;
	else return "None";
}
//命令行交互
int Interactive(char* out,int size)
{	
	printf("%s@%s:%s$ ",UserName(),HostName(),CurrentWorkDir());
	//获取用户输入
	fgets(out,size,stdin);
	out[strlen(out)-1] = 0;//将'\n'修改为'0'
	return strlen(out);
}
//切割字符串
void Split(char* in)
{
	int i = 0;
	argv[i++] = strtok(in,SPC);
	while(argv[i++] = strtok(NULL,SPC));
}
//执行指令
void Execute()
{
	pid_t id = fork();
	if(id == 0)
	{
		//程序替换，子进程执行命令
		execvp(argv[0],argv);
		exit(1);
	}

	pid_t rid = waitpid(id,NULL,0);
}
//执行内建指令
int BuildinCmd()
{
	//判断是否为内建指令，如果是，则返回1,否则返回0
	//并且执行内建指令
	//此处只列举cd这一条内建指令
	int ret = 0;
	if(strcmp("cd",argv[0])== 0)
	{
	   // cd *** | cd 
		char* Target = argv[1];
		if(!Target) Target = getenv("HOME");

		chdir(Target);
		
		//关联环境变量，格式化信息会输出到pwd字符数组中
		char tmp[999];
		getcwd(tmp,999);
		snprintf(pwd,SIZE,"PWD=%s",tmp);
		putenv(pwd);
		ret = 1;
	}
	if(strcmp("export",argv[0])==0)
	{
		ret = 1;
		if((argv[1]))
		{
		   strcpy(env,argv[1]);
	  	   putenv(env);
		}
	}
	return ret;
}
int main()
{
	while(1)
	{
    	char commandline[SIZE];
    	//1.打印命令行信息
    	int i = Interactive(commandline,SIZE);
		//如果是空串，则不做后续步骤
		if(i == 0) continue;
    	//2.切割字符串
    	Split(commandline);
    //	for(int i = 0; argv[i];++i)
    //	{
    //		printf("argv[%d]:%s\n",i,argv[i]);
    //	}

	    //3.执行内建指令
		 i = BuildinCmd();
		if(i) continue;
    	//4.执行命令
    	Execute();
	}
	return 0;
}
